#include <iostream>
#include <functional>
#include <memory>

#include "TcpServer.hpp"
#include "Protocol.hpp"
#include "CalCulate.hpp"

using namespace std;

void usage(string proc)
{
    cout << "Usage:\n\t" << proc << " local_port\n"
         << endl;
}
using call_back_t = function<Response(const Request &req)>;  //结果函数
class Service
{
public:
    Service(call_back_t cb) : _cb(cb)
    {
    }
    void ServiceHander(sock_sptr sockptr, InetAddr client)
    {
        int sockfd = sockptr->sockfd();
        Log(DEBUG, "get a new link, info %s:%d, fd : %d\n", client.ip().c_str(), client.port(), sockfd);
        string clientaddr = "[" + client.ip() + ":" + to_string(client.port()) + "] # ";
        string in;
        while (1)
        {
            sleep(5);
            // 读消息
            Request req;
            int n = sockptr->Recv(&in);
            if (n < 0) 
            {
                Log(DEBUG, "client %s quit\n", clientaddr.c_str());
                break;
            }
            // 分析数据，确定完整报文
            string package;
            while (true)
            {
                sleep(1);
                package = Decode(in);
                if (package.empty())
                    break;
                std::cout << "------------------------begin---------------" << std::endl;
                cout << "resq string: " << package << endl;
                // 完整的数据->反序列化
                req.Deserialization(package);
                // 进行业务处理
                Response resp = _cb(req);
                //将结果进行序列化
                // 发送到服务端进行处里，然后发送给客服端
                string send_str;
                resp.Serialization(&send_str);

                cout << "resp Serialization: " << endl;
                cout << send_str << endl;

                send_str = Encode(send_str);
                cout << "resp Encode:" << endl;
                cout << send_str << endl;

                sockptr->Send(send_str);
            }
        }
    }

private:
    call_back_t _cb;
};
int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        usage(argv[0]);
        exit(1);
    }
    uint16_t port = stoi(argv[1]);
   // daemon(0, 0);//让他成为守护进程，后台一直运行
    EnableScreen();
    Calculate cal;
    Service calservice(std::bind(&Calculate::Excute, &cal, std::placeholders::_1));
    io_service_t service = bind(&Service::ServiceHander, &calservice, std::placeholders::_1, std::placeholders::_2);
    std::unique_ptr<TcpServer> tsvr = std::make_unique<TcpServer>(port, service);

    tsvr->Loop();
    return 0;
}
